﻿using System.Collections;
using System.Security.Cryptography;
using System;
using System.Text;
using UnityEngine;

/// <summary>
/// 131203 hikim
/// </summary>
public class HMAC
{

    public static readonly HMAC Instance = new HMAC();

    private readonly HMACSHA1 crypto = new HMACSHA1();

    private HMAC()
    {
        string key = "hikim" + SystemInfo.deviceUniqueIdentifier + "hikim";
        byte[] bytes = Common.Encoding.GetBytes(key);
        Init(bytes);
    }

    public HMAC(string base64key)
    {
        Init(base64key);
    }

    public HMAC(byte[] key)
    {
        Init(key);
    }

    public void Init(string base64key)
    {
        this.Init(Convert.FromBase64String(base64key));
    }

    public void Init(byte[] key)
    {
        this.crypto.Key = key;
    }

    public string ComputeHashToBase64(string data)
    {
        return Convert.ToBase64String(ComputeHash(data));
    }

    public byte[] ComputeHash(string data)
    {
        if (string.IsNullOrEmpty(data))
            return null;
        byte[] bytes = Common.Encoding.GetBytes(data);
        return ComputeHash(bytes);
    }

    public string ComputeHashToBase64(byte[] data)
    {
        return Convert.ToBase64String(ComputeHash(data));
    }

    public byte[] ComputeHash(byte[] data)
    {
        return crypto.ComputeHash(data);
    }

    public bool Verify(string base64data, string base64hash)
    {
        if (string.IsNullOrEmpty(base64data) || string.IsNullOrEmpty(base64hash))
            return false;
        byte[] data = Convert.FromBase64String(base64data);
        byte[] hash = Convert.FromBase64String(base64hash);
        return Verify(data, hash);
    }

    public bool Verify(byte[] data, byte[] hash)
    {
        return CompareBytes(crypto.ComputeHash(data), hash);
    }

    public bool CompareBytes(byte[] a, byte[] b)
    {
        if (a.Length != b.Length)
            return false;

        for (int i = 0; i < a.Length; i++)
        {
            if (a[i] != b[i])
                return false;
        }
        return true;
    }
}
